//
// Created by qinzhou on 23-4-20.
//

#ifndef MEMORYPOOLMANAGER_H
#define MEMORYPOOLMANAGER_H

#include "MemoryPool.h"
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cxxabi.h>
#include "Any.h"

using namespace std;
using namespace MEM;

class MemoryManager {
public:
    static MemoryManager* GetInstance()
    {
	static MemoryManager instance;
	return &instance;
    }
    
    template<class T>
    std::shared_ptr<MemoryPool<T>> GetMemoryPool()
    {
	std::string key = TypeName<T>();
        if (m_typeArray.find(key) != m_typeArray.end()) {
	    std::cout << "find pool\n";
	    return m_typeArray[key].AnyCast<std::shared_ptr<MemoryPool<T>>>();
        }
        auto pool = std::make_shared<MemoryPool<T>>();
    	m_typeArray[key] = pool;
        return pool;
    }
    
    void Clear()
    {
	m_typeArray.clear();
    }
    
private:
    const char* DemangleAlloc(char const* name) {
	int status = 0;
	std::size_t size = 0;
	return abi::__cxa_demangle(name, nullptr, &size, &status);
    }
    
    template<class T> std::string TypeName()
    {
	std::string name(DemangleAlloc(typeid(T).name()));
	if constexpr (std::is_const_v<std::remove_reference_t<T>>) {
	    name += " const";
	}
	if constexpr (std::is_rvalue_reference_v<std::remove_reference_t<T>>) {
	    name += " &&";
	}
	else if constexpr (std::is_lvalue_reference_v<T>) {
	    name += " &";
	}
	return name;
    }
private:
    std::map<std::string, Any> m_typeArray;
};

#endif //MEMORYPOOLMANAGER_H
